package com.yc.auth.controller;

import cn.dev33.satoken.stp.SaTokenInfo;
import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.yc.annotation.AnonymousAccess;
import com.yc.api.CommonResult;
import com.yc.base.BaseController;
import com.yc.helper.LoginHelper;
import com.yc.menu.entity.Menu;
import com.yc.menu.service.IMenuService;
import com.yc.service.IRedisService;
import com.yc.user.service.IUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import java.io.Serial;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequiredArgsConstructor
@RequestMapping("v1/auth")
@Api(value = "AuthController", tags = "登录验证")
public class AuthController extends BaseController {

    private final IRedisService redisService;
    private final IUserService userService;
    private final IMenuService menuService;

    @Value("${loginCode.expiration}")
    private Long loginCodeExpiration;
    @Value("${loginCode.code-key}")
    private String loginCodeKey;
    @Value("${sa-token.token-prefix}")
    private String tokenPrefix;

    @AnonymousAccess
    @PostMapping("/login")
    @ApiOperation(value = "登录", notes = "登录")
    public CommonResult<?> login() {
        JSONObject params = getParams();
        String username = params.getStr("username", null);
        String password = params.getStr("password", null);
        String unique = params.getStr("unique", null);
        String code = params.getStr("code", null);
        if (StrUtil.isBlank(username) || StrUtil.isBlank(password)
                || StrUtil.isBlank(unique) || StrUtil.isBlank(code)) {
            return CommonResult.validateFailed();
        }
        // 查询验证码
        String rCode = (String) redisService.get(unique);
        // 清除验证码
        redisService.del(unique);

        if (StringUtils.isBlank(rCode)) {
            return CommonResult.failed("验证码不存在或已过期");
        }
        if (!code.equalsIgnoreCase(rCode)) {
            return CommonResult.failed("验证码错误");
        }

        SaTokenInfo saTokenInfo = userService.login(username, password);

        userService.updateLastLoginTime(LoginHelper.getUserId());
        if (saTokenInfo == null) {
            return CommonResult.validateFailed("用户名或密码错误");
        }
        Map<String, String> tokenMap = new HashMap<>();
        tokenMap.put("token", String.format("%s %s", tokenPrefix, saTokenInfo.getTokenValue()));

        return CommonResult.success(tokenMap);
    }

    @ApiOperation(value = "登出功能")
    @PostMapping(value = "/logout")
    @ResponseBody
    public CommonResult<?> logout() {
        LoginHelper.logout();
        return CommonResult.success();
    }

    @ApiOperation(value = "是否登录")
    @PostMapping(value = "/isLogin")
    @ResponseBody
    public CommonResult<?> isLogin() {
        if (LoginHelper.isLogin()) {
            return CommonResult.success();
        }
        return CommonResult.unauthorized(null);
    }

    @PostMapping("/permission")
    @ApiOperation(value = "获取MenuPermission列表", notes = "获取MenuPermission列表")
    public CommonResult<?> permission() {
        List<Menu> menuList = menuService.selectMenuPermission(LoginHelper.getUserId());
        return CommonResult.success(menuList);
    }

    @AnonymousAccess
    @PostMapping(value = "/code")
    @ApiOperation(value = "获取验证码", notes = "获取验证码")
    public CommonResult<?> getCode() {
        LineCaptcha captcha = CaptchaUtil.createLineCaptcha(110, 35, 4, 0);
        String result = captcha.getCode();
        String unique = loginCodeKey + IdUtil.simpleUUID();
        // 保存
        redisService.set(unique, result, loginCodeExpiration);
        // 验证码信息
        HashMap<String, Object> imgResult = new HashMap<>(2) {
            @Serial
            private static final long serialVersionUID = -8554472494977276148L;

            {
                put("img", captcha.getImageBase64Data());
                put("unique", unique);
            }
        };

        return CommonResult.success(imgResult);
    }
}
